package com.junxonline.plat.service.user.impl;

import com.junxonline.plat.dao.model.Position;
import com.junxonline.plat.dao.model.Role;
import com.junxonline.plat.dao.model.User;
import com.junxonline.plat.dao.repository.PositionRepository;
import com.junxonline.plat.dao.repository.RoleRepository;
import com.junxonline.plat.dao.repository.UserRepository;
import com.junxonline.plat.dao.vo.PageVO;
import com.junxonline.plat.dao.vo.QueryUserVO;
import com.junxonline.plat.dao.vo.UserVO;
import com.junxonline.common.util.CommonUtils;
import com.junxonline.plat.service.user.UserService;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
@Transactional
public class UserServiceImpl implements UserService {

    private Logger logger = LogManager.getLogger();

    @Autowired
    private UserRepository userRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private PositionRepository positionRepository;

    /**
     * 获取用户数据
     *
     * @param vo
     * @return
     */
    @Override
    public User getUser(QueryUserVO vo) {
        User user = userRepository.findByUserId(vo.getUserId());
        // 触发懒加载
        user.getPositions();

        return user;
    }

    /**
     * 筛选查询用户
     *
     * @param pageVO
     * @param vo
     * @return
     */
    @Override
    public PageVO queryUser(PageVO pageVO, QueryUserVO vo) {
        PageRequest pageRequest = PageRequest.of(pageVO.getPage() - 1, pageVO.getLimit(), new Sort(Sort.Direction.ASC, "userId"));

        Page<User> page = userRepository.findAll(new Specification<User>() {
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                List<Predicate> params = new ArrayList<>();
                String username = vo.getUsername();
                String nickname = vo.getNickname();
                Integer sex = vo.getSex();
                String createTime = vo.getCreateTime();
                Integer status = vo.getStatus();

                if (CommonUtils.isNotEmpty(username)) {
                    params.add(criteriaBuilder.like(root.get("username"), "%" + username + "%"));
                }

                if (CommonUtils.isNotEmpty(nickname)) {
                    params.add(criteriaBuilder.like(root.get("nickname"), "%" + nickname + "%"));
                }

                if (CommonUtils.isNotEmpty(sex)) {
                    params.add(criteriaBuilder.equal(root.get("sex"), sex));
                }

                if (CommonUtils.isNotEmpty(createTime)) {
                    params.add(criteriaBuilder.like(root.get("createTime").as(String.class), "%" + createTime + "%"));
                }

                if (CommonUtils.isNotEmpty(status)) {
                    params.add(criteriaBuilder.equal(root.get("status"), status));
                }

                return criteriaBuilder.and(params.toArray(new Predicate[params.size()]));
            }
        }, pageRequest);

        List<User> users = page.getContent();

        for (User user : users) {

            // 替换用户性别
            switch (user.getSex()) {
                case 0:
                    user.setSexString("男");
                    break;
                case 1:
                    user.setSexString("女");
                    break;
                default:
                    break;
            }

            // 替换用户状态
            switch (user.getStatus()) {
                case 0:
                    user.setStatusString("<span class=\"layui-badge layui-bg-green\">启用</span>");
                    break;
                case 1:
                    user.setStatusString("<span class=\"layui-badge\">禁用</span>");
                    break;
                default:
                    break;
            }

        }

        pageVO.setTotal(page.getTotalElements());
        pageVO.setData(users);

        return pageVO;
    }

    /**
     * 添加用户
     *
     * @param vo
     * @return
     */
    @Override
    public boolean addUser(UserVO vo) {

        User user = new User();
        user.setUsername(vo.getUsername());
        user.setPassword(vo.getPassword());
        user.setNickname(vo.getNickname());
        user.setSex(vo.getSex());
        user.setPhone(vo.getPhone());
        user.setEmail(vo.getEmail());
        user.setDescription(vo.getDescription());
        user.setCreateTime(new Date());
        user.setStatus(vo.getStatus());

        userRepository.save(user);

        return true;
    }

    /**
     * 修改用户
     *
     * @param vo
     * @return
     */
    @Override
    public boolean editUser(UserVO vo) {

        User user = userRepository.findByUserId(vo.getUserId());

        user.setUserId(vo.getUserId());
        user.setUsername(vo.getUsername());
        user.setPassword(vo.getPassword());
        user.setNickname(vo.getNickname());
        user.setSex(vo.getSex());
        user.setPhone(vo.getPhone());
        user.setEmail(vo.getEmail());
        user.setDescription(vo.getDescription());
        user.setStatus(vo.getStatus());

        userRepository.save(user);

        return true;
    }

    /**
     * 删除用户
     *
     * @param userIds
     * @return
     */
    @Override
    public boolean delUser(Long[] userIds) {

        List<User> users = userRepository.findByUserIdIn(userIds);

        for (User user : users) {

            List<Position> positions = user.getPositions();

            // 删除与该用户相关联的中间表的所有部门岗位数据
            for (Position position : positions) {
                Long positionId = position.getPositionId();
                userRepository.deleteUserPositionIn(user.getUserId(), positionId);
            }

            List<Role> roles = user.getRoles();

            // 删除与该用户相关联的中间表的所有角色数据
            for (Role role : roles) {
                Long roleId = role.getRoleId();
                userRepository.deleteUserRoleIn(user.getUserId(), roleId);
            }

            // 再删除用户
            userRepository.delete(user);

        }

        return true;
    }

    /**
     * 设置角色
     *
     * @param userIds
     * @param roleIds
     * @return
     */
    @Override
    public boolean setRole(Long[] userIds, Long[] roleIds) {

        // 先校验角色id集合
        List<Role> roles = roleRepository.findByRoleIdIn(roleIds);

        // 校验用户id
        List<User> users = userRepository.findByUserIdIn(userIds);

        // 删除与该用户关联的所有角色数据
        for (User user : users) {

            List<Role> deleteRoles = user.getRoles();

            for (Role role : deleteRoles) {
                userRepository.deleteUserRoleIn(user.getUserId(), role.getRoleId());
            }

        }

        for (User user : users) {

            // 再添加新的角色数据
            for (Role role : roles) {
                userRepository.saveUserRoleIn(user.getUserId(), role.getRoleId());
            }

        }

        return true;
    }

}
